int hueR = floor(random(0, 255));
int hueG = floor(random(0, 255));
int hueB = floor(random(0, 255));
int valueR = hueR;
int valueG = hueG;
int valueB = hueB;

boolean stale = true;
int height = 150;
int valueSaturationWdith = 150;
int hueWidth = 30;
int width = valueSaturationWdith + hueWidth;

// Colors for the hue control
ArrayList colors = new ArrayList();

void setup() {	
	size(width, height);
	smooth();
	colors.add(color(255, 0, 0));
	colors.add(color(255, 0, 255));
	colors.add(color(0, 0, 255));
	colors.add(color(0, 255, 255));
	colors.add(color(0, 255, 0));
	colors.add(color(255, 255, 0));
	colors.add(color(255, 0, 0));
}

void draw() {
	if (!stale) {
		return;
	}
	loadPixels();  
	for (int x = 0; x < valueSaturationWdith; x++) {
	  for (int y = 0; y < height; y++) {
	    int loc = x + (y * width);
	    pixels[loc] = getSaturationValueColor(
	    	x, y, valueSaturationWdith, height, hueR, hueG, hueB);
	  }
	}
	for (int x = 0; x < hueWidth; x++) {
	  for (int y = 0; y < height; y++) {
	    int loc = (x + valueSaturationWdith) + (y * width);
	    pixels[loc] = getHueColor(x, y, hueWidth, height);
	  }
	}
	updatePixels(); 
	stale = false;
}

void mousePressed() {
	if (mouseX <= valueSaturationWdith) {
		setCurrentColor();
	} else {
		setHueColor();
	}	
}

void setCurrentColor() {
	color newColor = getSaturationValueColor(
	    mouseX, mouseY, valueSaturationWdith, height, hueR, hueG, hueB);
	valueR = red(newColor);
	valueG = green(newColor);
	valueB = blue(newColor);
}

void setHueColor() {
	color newColor = getHueColor(mouseX, mouseY, hueWidth, height);
	hueR = red(newColor);
	hueG = green(newColor);
	hueB = blue(newColor);
	valueR = hueR;
	valueG = hueG;
	valueB = hueB;
	stale = true;
}

color getHueColor(int x, int y, int w, int h) {	
	float yp = y / h;
	int nColors = colors.size() - 1;
	
	// Choose the two colors to interpolate between.
	int firstColorIndex = floor(nColors * yp);
	int secondColorIndex = firstColorIndex + 1;
	if (secondColorIndex > colors.size() - 1) {
		secondColorIndex = 0;
	}	
	color first = colors.get(firstColorIndex);
	color second = colors.get(secondColorIndex);
	
	// Compute the percentage between the two colors.
	float bandWidth = h / nColors;
	int localY = y % bandWidth;
	float localP = localY / bandWidth;
	
	// Interpolate!
	int r = red(second) * localP + red(first) * (1 - localP);
	int g = green(second) * localP + green(first) * (1 - localP);
	int b = blue(second) * localP + blue(first) * (1 - localP);
	return color(r, g, b);
}

color getSaturationValueColor(int x, int y, int w, int h, int br, int bg, int bb) {
	// percentages for x and y
	float px = x / w;
	float py = y / h;

	int r = br + ((255 - br) * (1 - px));
	int g = bg + ((255 - bg) * (1 - px));
	int b = bb + ((255 - bb) * (1 - px));

	r = r - (r * py);
	g = g - (g * py);
	b = b - (b * py);
	return color(r, g, b);
}

String getColorValue() {
	return "rgb(" + valueR + "," + valueG + "," + valueB + ")";
}